home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / netmail / rnr214.zip / RNRMAIN.PAS < prev    next >
Pascal/Delphi Source File  |  1996-02-01  |  40KB  |  1,469 lines

  1. unit rnrmain;
  2.  
  3. {
  4.  
  5. rnrmain.pas - rnr main (to keep from recompiling huge rnr.pas)
  6.  
  7. }
  8.  
  9. {$I rnr-def.pas}
  10.  
  11. interface
  12.  
  13. uses dos,crt,genericf,rnrglob,rnrconf,rnrfunc,rnrselb,rnrio,
  14.   rnrproc,rnrkill,rnrfile,rnrnov
  15.  
  16. {$ifdef timeout}
  17.  
  18. ,rnrtime
  19.  
  20. {$endif}
  21.  
  22. {$ifdef charset}
  23.  
  24. ,rnrchar
  25.  
  26. {$endif}
  27.  
  28. {$ifdef mouse}
  29.  
  30. ,mouse   {see rnrmous.pas}
  31.  
  32. {$endif}
  33.  
  34. ;
  35.  
  36.  
  37. procedure sethash(var h: hashedt; s: string);
  38. procedure swapi(var i,j: integer);
  39. procedure swapart(a,b: integer);
  40. procedure sortitall;
  41. procedure readinarts;
  42. procedure groupinit;
  43.  
  44. implementation
  45.  
  46. procedure sethash;
  47.  
  48. var
  49.   i: integer;
  50.   atat: integer;
  51. {$ifdef oldhash}
  52.   ls,rs: integer;
  53. {$endif}
  54.   leng: integer;
  55.   l: integer;
  56.   startaft: integer;
  57.  
  58. begin
  59. {$ifdef oldhash}
  60.   for i := 1 to 6 do
  61.     h[i] := 0;
  62.  
  63.   atat := pos('@',s);
  64.   if atat=0 then
  65.     begin
  66. {leave malformed ones alone}
  67.     end
  68.   else
  69.     begin
  70. {assume all message-ids are at least 6 chars long - a@b.cd is}
  71.       ls := atat-6;
  72.       rs := atat+1;
  73. {handle these specially - the last bunch of stuff is always the same!}
  74.       if pos(newsreadername,s)>0 then
  75.         ls := 10;
  76.       if ls<1 then
  77.         ls := 1;
  78.       if atat>length(s)-5 then
  79.         rs := length(s)-5;
  80.       for i := 1 to 3 do
  81.         h[i] := 16*( (ord(s[ls+i*2-1])) and 15)+( (ord(s[ls+i*2])) and 15);
  82.       for i := 1 to 3 do
  83.         h[i+3] := 16*( (ord(s[rs+i*2-1])) and 15)+( (ord(s[rs+i*2])) and 15);
  84.     end;
  85. {$endif}
  86.  
  87.   h[1] := 0;
  88.   h[2] := 0;
  89.   atat := pos('@',s);
  90.   if atat=0 then
  91.     begin
  92. {leave malformed ones alone}
  93.     end
  94.   else
  95.     begin
  96.       leng := length(s);
  97.       l := min(16,leng);
  98.  
  99.       for i := 1 to l do
  100.         if odd(ord(s[i])) then
  101.           h[1] := (h[1] shl 1)+1
  102.         else
  103.           h[1] := h[1] shl 1;
  104.  
  105.       l := min(16,leng);
  106.  
  107.       startaft := leng-l;
  108.       if startaft>atat then
  109.         startaft := atat;
  110.  
  111.       for i := 1 to l do
  112.         if odd(ord(s[startaft+i])) then
  113.           h[2] := (h[2] shl 1)+1
  114.         else
  115.           h[2] := h[2] shl 1;
  116.     end;
  117.  
  118. {$ifdef testhash}
  119.  
  120. {
  121. writeln('hashed "',s,'" to ',h[1]:5,' ',h[2]:5);
  122. }
  123.  
  124. {$endif}
  125.  
  126. end;
  127.  
  128. procedure swapi;
  129.  
  130. var
  131.   t: integer;
  132.  
  133. begin
  134.   t := i;
  135.   i := j;
  136.   j := t;
  137. end;
  138.  
  139. procedure swapart;
  140.  
  141. var
  142.   temparticlep: articlept;
  143. {
  144.   tempsubj: subjstringt;
  145.   tempfilename: fnstringt;
  146.   tempdate: datet;
  147.   tempindents: byte;
  148.   tempsizeink: byte;
  149.   tempfrom: fromstringt;
  150. }
  151.  
  152. {don't need to worry about hashing or canon stuff - by this time, not needed}
  153.  
  154. begin
  155.   temparticlep := articles[a];
  156.   articles[a] := articles[b];
  157.   articles[b] := temparticlep;
  158.  
  159. {
  160.   tempsubj := basesubjs[a];
  161.   tempfilename := filenamesp^[a];
  162.   tempdate := datesp^[a];
  163.   tempindents := indents[a];
  164.   tempsizeink := sizeink[a];
  165.   tempfrom := fromsp^[a];
  166.  
  167.   basesubjs[a] := basesubjs[b];
  168.   filenamesp^[a] := filenamesp^[b];
  169.   datesp^[a] := datesp^[b];
  170.   indents[a] := indents[b];
  171.   sizeink[a] := sizeink[b];
  172.   fromsp^[a] := fromsp^[b];
  173.  
  174.   basesubjs[b] := tempsubj;
  175.   filenamesp^[b] := tempfilename;
  176.   datesp^[b] := tempdate;
  177.   indents[b] := tempindents;
  178.   sizeink[b] := tempsizeink;
  179.   fromsp^[b] := tempfrom;
  180. }
  181. end;
  182.  
  183. procedure sortitall;
  184.  
  185. type
  186.   intptrst=array[1..maxarts] of integer;
  187.  
  188. var
  189.   i,j: integer;
  190.  
  191.   currart: integer;
  192.  
  193.   dateptrs,subjptrs,finalptrs,revfinalptrs: intptrst;
  194.  
  195.   dateptrlookingat: integer;
  196.   finalptrsdone: integer;
  197.  
  198.   thisthreadfirstfinalptr: integer;
  199.   currsubjptr: integer;
  200.   foundnewsubj: boolean;
  201.   currsubj: subjstringt;
  202.   currcanonfirstchar: char;
  203.  
  204.   step: integer;
  205.   base: integer;
  206.   lowpos: integer;
  207.   highpos: integer;
  208.  
  209.   numartsdivstep: integer;
  210.  
  211. {$ifdef testsort}
  212.   debugf: text;
  213.   debugfn: string;
  214. {$endif}
  215.  
  216. begin
  217.  
  218. {first sort by date, then for each oldest article, take the rest of the}
  219. {articles in that thread together, sorting within the thread only}
  220.  
  221.   for i := 1 to numarts do
  222.     dateptrs[i] := i;
  223.  
  224. {the dates equal but subjects not test is for comp.sources.* etc. v29i033}
  225. {hopefully will help part 1/6 posts too (eg alt.sources)}
  226.  
  227. {$define bubble}
  228. {$undef bubble}
  229.  
  230. {$ifdef bubble}
  231.  
  232.   for i := 1 to numarts-1 do
  233.     for j := i+1 to numarts do
  234.       if (articles[dateptrs[i]]^.date>articles[dateptrs[j]]^.date) then
  235.         swapi(dateptrs[i],dateptrs[j])
  236.       else if
  237.        (
  238.         (articles[dateptrs[i]]^.date=articles[dateptrs[j]]^.date)
  239.          and
  240.         xfirstsubjg
  241.          (
  242.           articles[dateptrs[i]]^.canonfirstchar,
  243.           articles[dateptrs[j]]^.canonfirstchar,
  244.           articles[dateptrs[i]]^.basesubject,
  245.           articles[dateptrs[j]]^.basesubject
  246.          )
  247.        ) then
  248.         swapi(dateptrs[i],dateptrs[j]);
  249.  
  250. {$else}
  251.  
  252. { 2047 is the lowest (power of 2)-1 which is > maxarts }
  253.   step := 2047;
  254.   while step>0 do
  255.     begin
  256.       if not quiet and (numarts>step) then
  257.         begin
  258.           xwritei(step);
  259.           xwrites('.');
  260.         end;
  261.  
  262.       numartsdivstep := numarts div step;
  263.  
  264.       for base := 1 to step do
  265.         for i := 0 to numartsdivstep-1 do
  266.           for j := i+1 to numartsdivstep do
  267.             begin
  268.               lowpos := base+i*step;
  269.               highpos := base+j*step;
  270.  
  271.               if highpos<=numarts then
  272.                 begin
  273.  
  274.                   if
  275.                    articles[dateptrs[lowpos]]^.date
  276.                    >
  277.                    articles[dateptrs[highpos]]^.date then
  278.                     swapi(dateptrs[lowpos],dateptrs[highpos])
  279.                   else
  280.                     if
  281.                      (articles[dateptrs[lowpos]]^.date=
  282.                      articles[dateptrs[highpos]]^.date)
  283.                       and
  284.                      xfirstsubjg
  285.                       (
  286.                        articles[dateptrs[lowpos]]^.canonfirstchar,
  287.                        articles[dateptrs[highpos]]^.canonfirstchar,
  288.                        articles[dateptrs[lowpos]]^.basesubject,
  289.                        articles[dateptrs[highpos]]^.basesubject
  290.                       )
  291.                      then
  292.                       swapi(dateptrs[lowpos],dateptrs[highpos]);
  293.  
  294.                 end;
  295.             end;
  296.  
  297.       step := step div 2;   {it's vital that 1 div 2=0 here}
  298.     end;
  299.  
  300. {$endif}
  301.  
  302.   notquiets(':');
  303.  
  304. {$ifdef testsort}
  305.   if showdebug('sort') then
  306.     begin
  307.       debugfn := '\debug.th';
  308.       writeln('using ',debugfn);
  309.       assign(debugf,debugfn);
  310.       rewrite(debugf);
  311.  
  312.       writeln(debugf,'date ordering:');
  313.       for i := 1 to numarts do
  314.         writeln(debugf,dateptrs[i]:5,' ',
  315.          articles[dateptrs[i]]^.filename:5,' ',
  316.          articles[dateptrs[i]]^.basesubject);
  317.       writeln(debugf);
  318.       writeln(debugf);
  319.     end;
  320. {$endif}
  321.  
  322.   for i := 1 to numarts do
  323.     subjptrs[i] := i;
  324.  
  325. {$ifdef bubble}
  326.  
  327.   for i := 1 to numarts-1 do
  328.     begin
  329.       notquiets('.');
  330.  
  331.       for j := i+1 to numarts do
  332.         begin
  333.           if xfirstsubjg
  334.            (
  335.             articles[subjptrs[i]]^.canonfirstchar,
  336.             articles[subjptrs[j]]^.canonfirstchar,
  337.             articles[subjptrs[i]]^.basesubject,
  338.             articles[subjptrs[j]]^.basesubject
  339.            ) then
  340.             swapi(subjptrs[i],subjptrs[j]);
  341.         end;
  342.     end;
  343.  
  344. {$else}
  345.  
  346. { 2047 is the lowest (power of 2)-1 which is > maxarts }
  347.   step := 2047;
  348.   while step>0 do
  349.     begin
  350.       if not quiet and (numarts>step) then
  351.         begin
  352.           xwritei(step);
  353.           xwrites('.');
  354.         end;
  355.  
  356.       numartsdivstep := numarts div step;
  357.  
  358.       for base := 1 to step do
  359.         for i := 0 to numartsdivstep-1 do
  360.           for j := i+1 to numartsdivstep do
  361.             begin
  362.               lowpos := base+i*step;
  363.               highpos := base+j*step;
  364.  
  365.               if highpos<=numarts then
  366.                 if xfirstsubjg
  367.                  (
  368.                   articles[subjptrs[lowpos]]^.canonfirstchar,
  369.                   articles[subjptrs[highpos]]^.canonfirstchar,
  370.                   articles[subjptrs[lowpos]]^.basesubject,
  371.                   articles[subjptrs[highpos]]^.basesubject
  372.                  ) then
  373.                   swapi(subjptrs[lowpos],subjptrs[highpos]);
  374.             end;
  375.  
  376.       step := step div 2;   {it's vital that 1 div 2=0 here}
  377.     end;
  378.  
  379. {$endif}
  380.  
  381.   notquiets(':');
  382.  
  383. {$ifdef testsort}
  384.   if showdebug('sort') then
  385.     begin
  386.       writeln(debugf,'subject ordering:');
  387.       for i := 1 to numarts do
  388.         writeln(debugf,subjptrs[i]:5,' ',
  389.          articles[subjptrs[i]]^.filename:5,' ',
  390.          articles[subjptrs[i]]^.basesubject);
  391.       writeln(debugf);
  392.       writeln(debugf);
  393.     end;
  394. {$endif}
  395.  
  396. {sort via finalptrs indirection to prevent extra swapping}
  397.  
  398. {$ifdef testsort}
  399.   for i := 1 to numarts do
  400.     finalptrs[i] := -1;
  401.   for i := 1 to numarts do
  402.     revfinalptrs[i] := -1;
  403. {$endif}
  404.  
  405. {major sort: oldest article first, and all in its thread}
  406.  
  407.   dateptrlookingat := 0;
  408.   finalptrsdone := 0;
  409.   while finalptrsdone<numarts do
  410.     begin
  411.       inc(dateptrlookingat);
  412.  
  413. {skip over ones we've flagged as done}
  414.  
  415.       if dateptrs[dateptrlookingat]>0 then
  416.         begin
  417.  
  418.           notquiets('.');
  419.  
  420. {dateptrs[dateptrlookingat] now points to oldest article not yet done}
  421.  
  422.           currsubj := articles[dateptrs[dateptrlookingat]]^.basesubject;
  423.           currcanonfirstchar := canonicalfirstchar(currsubj);
  424.  
  425. {and currsubj is its subject -- now find all that match it}
  426.  
  427. {$ifdef testsort}
  428.   if showdebug('sort') then
  429.     writeln(debugf,'(oldest) curr (canon)subj=',
  430.      '(',currcanonfirstchar,')',currsubj);
  431. {$endif}
  432.  
  433.           currsubjptr := 1;
  434.  
  435.           currart := 0;
  436.           while currart<numarts do
  437.             begin
  438.               inc(currart);
  439.  
  440. {if <= currsubj, then set the pointer -- to the first that matches}
  441. {since subjptrs is the sorted subjects, it must match}
  442.  
  443. {$ifdef testsort}
  444. {$ifdef verbosetestsort}
  445.   if showdebug('sort') then
  446.     writeln(debugf,'currsubjptr--is it ',currart,'?  comparing:',
  447.      copy(articles[subjptrs[currart]]^.basesubject,1,32),'...',
  448.      right(articles[subjptrs[currart]]^.basesubject,8));
  449. {$endif}
  450. {$endif}
  451.  
  452.               if not xfirstsubjg
  453.                (
  454.                 currcanonfirstchar,
  455.                 articles[subjptrs[currart]]^.canonfirstchar,
  456.                 currsubj,
  457.                 articles[subjptrs[currart]]^.basesubject
  458.                ) then
  459.                 begin
  460.                   currsubjptr := currart;
  461.                   currart := numarts;
  462.                 end;
  463.             end;
  464.  
  465.           thisthreadfirstfinalptr := finalptrsdone+1;
  466.  
  467.           foundnewsubj := false;
  468.           while (finalptrsdone<numarts) and not foundnewsubj do
  469.             begin
  470.  
  471. {$ifdef testsort}
  472.   if showdebug('sort') then
  473.     begin
  474.               if currsubjptr>numarts then
  475.                 writeln(debugf,'gone off the end!  must be done this pass')
  476.               else
  477.                 begin
  478.                  if not subjseq(currsubj,
  479.                   articles[subjptrs[currsubjptr]]^.basesubject) then
  480.                    writeln(debugf,'method 1: found a new subject');
  481.                  if not xsubjseq(currcanonfirstchar,
  482.                   articles[subjptrs[currsubjptr]]^.canonfirstchar,
  483.                   currsubj,
  484.                   articles[subjptrs[currsubjptr]]^.basesubject) then
  485.                    writeln(debugf,'method 2: found a new subject');
  486.  
  487.                  if subjseq(currsubj,
  488.                   articles[subjptrs[currsubjptr]]^.basesubject)
  489.                  <>
  490.                   xsubjseq(currcanonfirstchar,
  491.                   articles[subjptrs[currsubjptr]]^.canonfirstchar,
  492.                   currsubj,
  493.                   articles[subjptrs[currsubjptr]]^.basesubject) then
  494.                    writeln(debugf,'ERROR method 1 and 2 disagree');
  495.  
  496.                  if xsubjseq(currcanonfirstchar,
  497.                   articles[subjptrs[currsubjptr]]^.canonfirstchar,
  498.                   currsubj,
  499.                   articles[subjptrs[currsubjptr]]^.basesubject) then
  500.                    begin
  501.                      writeln(debugf,'found equal: 1=',
  502.                       '(',currcanonfirstchar,')',currsubj);
  503.                      writeln(debugf,'             2=','(',
  504.                       articles[subjptrs[currsubjptr]]^.canonfirstchar,')',
  505.                       articles[subjptrs[currsubjptr]]^.basesubject);
  506.                    end;
  507.                 end;
  508.     end;
  509. {$endif}
  510.  
  511.               if currsubjptr>numarts then
  512.                 foundnewsubj := true
  513.               else if not xsubjseq
  514.                (
  515.                 currcanonfirstchar,
  516.                 articles[subjptrs[currsubjptr]]^.canonfirstchar,
  517.                 currsubj,
  518.                 articles[subjptrs[currsubjptr]]^.basesubject
  519.                ) then
  520.                 foundnewsubj := true
  521.               else
  522.                 begin
  523.  
  524. {$ifdef testsort}
  525.                   if revfinalptrs[subjptrs[currsubjptr]]<>-1 then
  526.                     begin
  527.                       writeln('already used subjptrs[',currsubjptr,']=',
  528.                        subjptrs[currsubjptr]);
  529.                       writeln(articles[subjptrs[currsubjptr]]^.basesubject);
  530.                       halt(1);
  531.                     end;
  532. {$endif}
  533.  
  534.                   inc(finalptrsdone);
  535.                   finalptrs[finalptrsdone] := subjptrs[currsubjptr];
  536.                   inc(currsubjptr);
  537.  
  538. {$ifdef testsort}
  539.   if showdebug('sort') then
  540.     writeln(debugf,'subject matches--add #',
  541.      finalptrsdone,' ',finalptrs[finalptrsdone],', fn ',
  542.      articles[finalptrs[finalptrsdone]]^.filename);
  543. {$endif}
  544.  
  545.                 end;
  546.             end;
  547.  
  548. {$ifdef testsort}
  549.   if showdebug('sort') then
  550.     begin
  551.       writeln(debugf,'currsubj=',currsubj);
  552.       writeln(debugf,'this chain, pre-ordering:');
  553.       for i := thisthreadfirstfinalptr to finalptrsdone do
  554.         write(debugf,finalptrs[i]:5,' ');
  555.       writeln(debugf);
  556.       for i := thisthreadfirstfinalptr to finalptrsdone do
  557.         write(debugf,articles[finalptrs[i]]^.filename:5,' ');
  558.     end;
  559. {$endif}
  560.  
  561.           for i := thisthreadfirstfinalptr to finalptrsdone-1 do
  562.             for j := i+1 to finalptrsdone do
  563.               if not firstartfirst(finalptrs[i],finalptrs[j]) then
  564.                 swapi(finalptrs[i],finalptrs[j]);
  565.  
  566. {$ifdef testsort}
  567.   if showdebug('sort') then
  568.     begin
  569.       writeln(debugf);
  570.       writeln(debugf,'this chain, post-ordering:');
  571.       for i := thisthreadfirstfinalptr to finalptrsdone do
  572.         write(debugf,finalptrs[i]:5,' ');
  573.       writeln(debugf);
  574.       for i := thisthreadfirstfinalptr to finalptrsdone do
  575.         write(debugf,articles[finalptrs[i]]^.filename:5,' ');
  576.       writeln(debugf);
  577.     end;
  578. {$endif}
  579.  
  580. {
  581.           notquiets('<');
  582. }
  583.  
  584. {
  585.   for the longest time, I didn't have the ``dateptrs[i]>0'' test in
  586.   here, which was really stupid.
  587. }
  588.  
  589.           for i := 1 to numarts do
  590.             if dateptrs[i]>0 then
  591.               if xsubjseq
  592.                (
  593.                 currcanonfirstchar,
  594.                 articles[dateptrs[i]]^.canonfirstchar,
  595.                 currsubj,
  596.                 articles[dateptrs[i]]^.basesubject
  597.                ) then
  598.  
  599.                 begin
  600.  
  601. {$ifdef testsort}
  602.                   if showdebug('sort') then
  603.                     begin
  604.                       writeln(debugf,'>>>');
  605.                       writeln(debugf,
  606.                        'setting dateptrs[',i,'] to ',-dateptrs[i]);
  607.                       writeln(debugf,'  curr=',currsubj);
  608.                       writeln(debugf,
  609.                        '  date=',articles[dateptrs[i]]^.basesubject);
  610.                       writeln(debugf,'<<<');
  611.                     end;
  612. {$endif}
  613.  
  614.                   dateptrs[i] := -dateptrs[i];
  615.                 end;
  616.  
  617. {
  618.           notquiets('>');
  619. }
  620.  
  621. {$ifdef testsort}
  622.   if showdebug('sort') then
  623.     begin
  624.       writeln(debugf);
  625.       writeln(debugf,'----------------');
  626.       writeln(debugf);
  627.     end;
  628. {$endif}
  629.  
  630.         end;
  631.     end;
  632.  
  633. {$ifdef testsort}
  634.   if showdebug('sort') then
  635.     begin
  636.       writeln(debugf,'the whole thing, pre-sorted:');
  637.       for i := 1 to numarts do
  638.         writeln(debugf,finalptrs[i]:5,' ',
  639.          articles[finalptrs[i]]^.filename:5,' ',
  640.          articles[finalptrs[i]]^.basesubject);
  641.       writeln(debugf);
  642.       writeln(debugf,'----------------');
  643.       writeln(debugf);
  644.  
  645.       for i := 1 to numarts do
  646.         begin
  647.           if (finalptrs[i]<1) or (finalptrs[i]>numarts) then
  648.             write(debugf,'ERROR: ');
  649.           writeln(debugf,'finalptrs[',i,']=',finalptrs[i]);
  650.         end;
  651. {$endif}
  652.  
  653.   for i := 1 to numarts do
  654.     revfinalptrs[i] := -1;
  655.  
  656.   for i := 1 to numarts do
  657.     revfinalptrs[finalptrs[i]] := i;
  658.  
  659. {$ifdef testsort}
  660.   if showdebug('sort') then
  661.     for i := 1 to numarts do
  662.       writeln(debugf,'revfinalptrs[',i,']=',revfinalptrs[i]);
  663.  
  664.   if showdebug('sort') then
  665.     writeln(debugf);
  666. {$endif}
  667.  
  668.   for i := 1 to numarts do
  669.     if revfinalptrs[i]<0 then
  670.       begin
  671.         writeln('ERROR: revfinalptrs[',i,']=',revfinalptrs[i]);
  672. {$ifdef testsort}
  673.         if showdebug('sort') then
  674.           close(debugf);
  675. {$endif}
  676.         halt(1);
  677.       end;
  678.  
  679.   for i := 1 to numarts-1 do
  680.     if finalptrs[i]<>i then
  681.       begin
  682.         swapart(i,finalptrs[i]);
  683.         finalptrs[revfinalptrs[i]] := finalptrs[i];
  684.         revfinalptrs[finalptrs[i]] := revfinalptrs[i];
  685.         finalptrs[i] := i;
  686.         revfinalptrs[i] := i;
  687.       end;
  688.  
  689. {$ifdef testsort}
  690.   if showdebug('sort') then
  691.     begin
  692.       writeln(debugf,'the whole thing, sorted:');
  693.       for i := 1 to numarts do
  694.         writeln(debugf,i:5,' ',
  695.          articles[i]^.filename:5,' ',
  696.          articles[i]^.basesubject);
  697.       writeln(debugf);
  698.       writeln(debugf,'----------------');
  699.       writeln(debugf);
  700.  
  701.       writeln('closing ',debugfn);
  702.       close(debugf);
  703.     end;
  704. {$endif}
  705.  
  706. end;
  707.  
  708. procedure readinarts;
  709.  
  710. var
  711.   dotnewsreadernamedot: string;
  712.   highestseen: articlefilenametype;
  713.   wroteanything: boolean;
  714.   fileinfo: searchrec;
  715.   iscaughtup: boolean;
  716.   rewoundapage: boolean;
  717.   startedwhereleftoff: boolean;
  718.  
  719.   morearticles: boolean;
  720.  
  721.   subject: string;
  722.   from: string;
  723.   headerto: string;
  724.   newsgroups: string;
  725.   messageid: string;
  726.   references: string;
  727.   inreplyto: string;
  728.  
  729.   basefilename: string;
  730.   filename: string;
  731.   filenum: articlefilenametype;
  732.   filesize: longint;
  733.  
  734.   datestr: string;
  735.   mailgroup: boolean;
  736.   bufferedkey: char;
  737.   i: integer;
  738.   workwithit: boolean;
  739.   readnomore: boolean;
  740.   highestfile: articlefilenametype;
  741.   mangledsubject: string;
  742.   trysource: string;
  743.   trysourcekind: sourcetype;
  744.   upsearchtext: string;
  745.   worthalook: boolean;
  746.   catchupunreadlastpageignore: char;
  747.  
  748.   ignorestring: string;
  749.  
  750.   hasoverview: boolean;
  751.  
  752.   waskilled: boolean;
  753.   wasantikilled: boolean;
  754.  
  755.     function searchsubjname: boolean;
  756.  
  757.     var
  758.       result: boolean;
  759.  
  760.     begin  {function searchsubjname}
  761.       result := false;
  762.  
  763.     {only subject and from and date are known at the point this is called}
  764.       if not result then
  765.         if searchinsubj then
  766.           result := textintext(upsearchtext,upper(subject));
  767.  
  768.       if not result then
  769.         if searchinname then
  770.           result := textintext(upsearchtext,upper(from));
  771.  
  772.       searchsubjname := result;
  773.     end;  {function searchsubjname}
  774.  
  775.     procedure showarticleprefix(basefilename: string);
  776.  
  777.     begin {showarticleprefix}
  778.       wroteanything := true;
  779.  
  780.       if justdots then
  781.         xwrites('.')
  782.       else
  783.         xwrites(basefilename);
  784.     end; {showarticleprefix}
  785.  
  786.     procedure showarticlesuffix;
  787.  
  788.     begin {showarticlesuffix}
  789.       if not justdots then
  790.         if wanderingnumbers then
  791.           xwrites(' ')
  792.         else
  793.           xwritess('         ',^M);
  794.     end; {showarticlesuffix}
  795.  
  796. begin  {procedure readinarts}
  797.   dotnewsreadernamedot := '.'+newsreadername+'.';
  798.  
  799.   unscannedarts := false;
  800.  
  801.   highestseen := 0;
  802.   wroteanything := false;
  803.  
  804.   startedwhereleftoff := false;
  805.   if lowestartsearched=impossiblylargeart then
  806.     begin
  807.       if readpagesback<>0 then
  808.         lowestartsearched := lmax(alreadyread-readpagesback*sellpp,0)
  809.       else
  810.         begin
  811.           lowestartsearched := alreadyread;
  812.           startedwhereleftoff := true;
  813.         end;
  814.     end;
  815.  
  816.   bufferedkey := ' ';
  817.  
  818.   upsearchtext := upper(searchtext);
  819.  
  820.   mailgroup := ismailgroup(currsource);
  821.  
  822.   if not mailgroup then
  823.     if currsourcekind=sourcegroup then
  824.       if entergroupcommand<>'' then
  825.         begin
  826.           notquietlns('running '+entergroupcommand+' '+currdir);
  827.           execviacomspec(entergroupcommand+' '+currdir);
  828. {}{}{}{}{ignore execresult?}
  829.           notquietlns('back from '+entergroupcommand);
  830.         end;
  831.  
  832.   rewoundapage := false;
  833.  
  834.   if mailagent and mailgroup then
  835.     begin
  836.       iscaughtup := true;
  837.  
  838. {note -- for mail groups, ignore the overview file}
  839.  
  840.       findfirst(withbackslash(currdir)+articlefilenamepattern,
  841.        archive,fileinfo);
  842.  
  843. {empty folders don't count -- if we couldn't find even ONE file, ignore}
  844.       if doserror<>0 then
  845.         iscaughtup := false;
  846.  
  847.       while (doserror=0) and iscaughtup do
  848.         begin
  849.           filenum := atol(fileinfo.name);
  850.           if (filenum>lowestartsearched) and isdigit(fileinfo.name[1]) then
  851.             iscaughtup := false;
  852.           findnext(fileinfo);
  853.         end;
  854.  
  855.       if iscaughtup then
  856.         begin
  857.           rewoundapage := true;
  858.           readpagesback := 1;
  859.           lowestartsearched := lmax(alreadyread-readpagesback*sellpp,0);
  860.  
  861.           if not quiet then
  862.             begin
  863.               xwrites('(1 page) ');
  864.               wroteanything := true;
  865.             end;
  866.         end;
  867.     end;
  868.  
  869.   readpagesback := 0;
  870.  
  871.   nextwhilereading := false;
  872.   readnomore := false;
  873.   highestart := 0;
  874.   highestfile := 0;
  875.  
  876.   if mailgroup or (currsourcekind<>sourcegroup) then
  877.     readunfiltered := true;
  878.  
  879.   if mailgroup then
  880.     antikilledonly := false;
  881.  
  882.   if not dexists(currdir) then
  883.     xwritelnsss('directory ',currdir,' does not exist');
  884.  
  885.   hasoverview := false;
  886.  
  887. {note -- for mail groups, ignore the overview file}
  888.  
  889.   if currsourcekind=sourcegroup then
  890.     if not mailgroup then
  891.       begin
  892.         overviewreset(currdir);
  893.         if fileresult=0 then
  894.           begin
  895.             hasoverview := true;
  896.             notquietlns('(using overview file)');
  897.           end;
  898.       end;
  899.  
  900.   if hasoverview then
  901.     begin
  902.       morearticles := not eofoverview;
  903.     end
  904.   else
  905.     begin
  906.       findfirst(withbackslash(currdir)+articlefilenamepattern,
  907.        archive,fileinfo);
  908.       morearticles := (doserror=0);
  909.     end;
  910.  
  911.   while morearticles and
  912.    (numarts<allocatedarts) and
  913.    not nextwhilereading and
  914.    not readnomore do
  915.     begin
  916.  
  917.       if xkeypressed then
  918.         begin
  919.           bufferedkey := xreadkey;
  920.           if bufferedkey='N' then
  921.             nextwhilereading := true
  922.           else if bufferedkey='O' then
  923.             readnomore := true
  924.           else if (bufferedkey='!') and trusted then
  925.             begin
  926.               shellout;
  927.             end
  928.           else if bufferedkey='Q' then
  929.             begin
  930. {}{} {should it use confirmquit here?}
  931.               nextwhilereading := true;
  932.               needtofindnextgroup := false;
  933.               currsource := '';
  934.             end;
  935.         end;
  936.  
  937.       if hasoverview then
  938.         readoverviewline;
  939.  
  940.       if hasoverview then
  941.         basefilename := nextoverviewitem
  942.       else
  943.         basefilename := fileinfo.name;
  944.  
  945.       filenum := atol(basefilename);
  946.       filename := withbackslash(currdir)+basefilename;
  947.  
  948.       if filenum>highestseen then
  949.         highestseen := filenum;
  950.  
  951.       worthalook := false;
  952.  
  953.       if not nextwhilereading and not readnomore and
  954.        (filenum>lowestartsearched) and isdigit(basefilename[1]) then
  955.         worthalook := true;
  956.  
  957. {need date for searchthedate possibly}
  958.  
  959.       subject := '(internal error)';
  960.       from := '(internal error)';
  961.       datestr := '(internal error)';
  962.  
  963.       if worthalook then
  964.         begin
  965.           if hasoverview then
  966.             begin
  967.               subject := nextoverviewitem;
  968.               from := nextoverviewitem;
  969.               datestr := nextoverviewitem;
  970.             end
  971.           else
  972.             begin
  973.               subject := getheaderline(filename,'subject:');
  974.               from := getheaderline(filename,'from:');
  975.               datestr := getheaderline(filename,'date:');
  976.             end
  977.         end;
  978.  
  979. {+24 is to handle different time zones}
  980.       if worthalook and searchthedate then
  981.         begin
  982.           if (rfcdateheadertodate(datestr)<searchdatelow) or
  983.            (rfcdateheadertodate(datestr)>searchdatehigh+24) then
  984.             worthalook := false;
  985.  
  986. {if not worthalook, then it was just date-searching that took it out}
  987.           if not worthalook then
  988.             begin
  989.               showarticleprefix(basefilename);
  990.               xwrites('d');
  991.               showarticlesuffix;
  992.             end;
  993.  
  994.         end;
  995.  
  996.       if worthalook and (searchinsubj or searchinname) then
  997.         begin
  998.           worthalook := searchsubjname;
  999.  
  1000. {if not worthalook, then it was just searching that took it out}
  1001.           if not worthalook then
  1002.             begin
  1003.               showarticleprefix(basefilename);
  1004.               if not highlightsearchhits then
  1005.                 xwrites('n');
  1006.               showarticlesuffix;
  1007.             end;
  1008.  
  1009.         end;
  1010.  
  1011.       if worthalook and (searchinheaders or searchinbody) then
  1012.         begin
  1013.           worthalook := false;
  1014.  
  1015.           if searchinheaders then
  1016.             worthalook := searchart(filename,upsearchtext,yesheadersearch);
  1017.  
  1018. {don't search body unless not found in headers}
  1019.           if not worthalook and searchinbody then
  1020.             worthalook := searchart(filename,upsearchtext,noheadersearch);
  1021.  
  1022. {if not worthalook, then it was just searching that took it out}
  1023.           if not worthalook then
  1024.             begin
  1025.               showarticleprefix(basefilename);
  1026.               if not highlightsearchhits then
  1027.                 xwrites('n');
  1028.               showarticlesuffix;
  1029.             end;
  1030.  
  1031.         end;
  1032.  
  1033.       if worthalook then
  1034.         begin
  1035.           messageid := '(internal error)';
  1036.           references := '(internal error)';
  1037.  
  1038.           if hasoverview then
  1039.             begin
  1040.               messageid := nextoverviewitem;
  1041.               references := nextoverviewitem;
  1042.               filesize := atol(nextoverviewitem);
  1043.               ignorestring := nextoverviewitem;  {lines}
  1044.  
  1045.               {
  1046.                 get newsgroups if you can, but don't be drastic
  1047.                 and go to disk and search the article itself unless necessary
  1048.               }
  1049.  
  1050.               newsgroups := getoverviewheader('newsgroups:');
  1051.               if (newsgroups='') and not readunfiltered then
  1052.                 newsgroups := getheaderline(filename,'newsgroups:');
  1053.             end
  1054.           else
  1055.             begin
  1056.               newsgroups := getheaderline(filename,'newsgroups:');
  1057.               filesize := fileinfo.size;
  1058.             end;
  1059.  
  1060. {some people put tabs in the Subject: line!  ick!}
  1061.  
  1062.           subject := expand(subject);
  1063.  
  1064.           if highlightsearchhits then
  1065.             begin
  1066.               if searchinheaders or searchinbody or
  1067.                searchinsubj or searchinname then
  1068.                 xhighvideo;
  1069.             end;
  1070.  
  1071.           showarticleprefix(basefilename);
  1072.  
  1073.           if highlightsearchhits then
  1074.             begin
  1075.               if searchinheaders or searchinbody or
  1076.                searchinsubj or searchinname then
  1077.                 xlowvideo;
  1078.             end;
  1079.  
  1080. {if there's from and newsgroups, but no subject, keep it in search}
  1081.  
  1082.           mangledsubject := nore(subject);
  1083.  
  1084.           if (mangledsubject='') and (from<>'') and (newsgroups<>'') then
  1085.             subject := 'No Subject - From '+from;
  1086.  
  1087.           if readunfiltered and (filesize<>0) and (mangledsubject='') then
  1088.             subject := 'No Subject - From '+from;
  1089.  
  1090.           if (mangledsubject='') and missingsubjectisok then
  1091.             subject := 'No Subject - From '+from;
  1092.  
  1093.           waskilled := false;
  1094.           wasantikilled := false;
  1095.           workwithit := true;
  1096.  
  1097. { if we can't find a subject at all, even a faked one, just ignore it }
  1098.  
  1099.           if subject='' then
  1100.             begin
  1101.               workwithit := false;
  1102.               xwrites('e');
  1103.             end;
  1104.  
  1105.           if workwithit and not readunfiltered then
  1106.             begin
  1107.               if alreadyseen(newsgroups) then
  1108.                 begin
  1109.                   workwithit := false;
  1110.                   xwrites('s');
  1111.                 end
  1112.               else
  1113.                 begin
  1114.                   waskilled := artkilled(subject,from,'',filename);
  1115.                   workwithit := not waskilled;
  1116.                   if waskilled then
  1117.                     xwrites('k');
  1118.                   if antikillevenkilled then
  1119.                     workwithit := true;
  1120.                 end;
  1121.             end;
  1122.  
  1123.           if workwithit then
  1124.             begin
  1125.  
  1126. {
  1127.   might have to undo this if it was killed and not antikilled, or if
  1128.   antikilled only but it wasn't antikilled
  1129. }
  1130.               inc(numarts);
  1131.               articles[numarts]^.filename := basefilename;
  1132.  
  1133. {
  1134.   use mangledsubject instead of articles[numarts]^.basesubject to prevent
  1135.   incorrect thread separation when Re: makes it go beyond subjstringt length
  1136. }
  1137.  
  1138. { changed 'Re: ' to 'Re:' - a LOT of broken systems out there! }
  1139.  
  1140.               mangledsubject := subject;
  1141.               articles[numarts]^.indents := 0;
  1142.               while upper(copy(mangledsubject,1,3))='RE:' do
  1143.                 begin
  1144.                   inc(articles[numarts]^.indents);
  1145.                   mangledsubject := ltrim(copy(mangledsubject,4,255));
  1146.                 end;
  1147.  
  1148.               articles[numarts]^.basesubject := mangledsubject;
  1149.               articles[numarts]^.canonfirstchar :=
  1150.                canonicalfirstchar(articles[numarts]^.basesubject);
  1151.  
  1152.               headerto := '';
  1153.               if (from=mailfrom) or (from=newsfrom) then
  1154.                 headerto := getheaderline(filename,'to:');
  1155.               if headerto=couldnotreadfilecookie then
  1156.                 headerto := '';
  1157.  
  1158.               if ((from=mailfrom) or (from=newsfrom)) and (headerto<>'') then
  1159.                 begin
  1160.                   articles[numarts]^.from := trim(ltrim(getfromname(headerto)));
  1161.                   if articles[numarts]^.from='' then
  1162.                     articles[numarts]^.from := getfromaddr(headerto)
  1163.                   else if length(articles[numarts]^.from)<=8 then
  1164.                     articles[numarts]^.from :=
  1165.                      articles[numarts]^.from+', '+getfromaddr(headerto);
  1166.                   articles[numarts]^.from := 'To:'+articles[numarts]^.from;
  1167.                 end
  1168.               else
  1169.                 begin
  1170.                   articles[numarts]^.from := trim(ltrim(getfromname(from)));
  1171.                   if articles[numarts]^.from='' then
  1172.                     articles[numarts]^.from := getfromaddr(from)
  1173.                   else if length(articles[numarts]^.from)<=8 then
  1174.                     articles[numarts]^.from :=
  1175.                      articles[numarts]^.from+', '+getfromaddr(from);
  1176.                 end;
  1177.  
  1178. { if size is too big, just store 255, otherwise round up to nearest kilobyte }
  1179.               if filesize>255*1024 then
  1180.                 articles[numarts]^.sizeink := 255
  1181.               else
  1182.                 articles[numarts]^.sizeink :=
  1183.                  longint(filesize+1023) div longint(1024);
  1184.  
  1185.               if not hasoverview then
  1186.                 datestr := getheaderline(filename,'date:');
  1187.  
  1188.               articles[numarts]^.date := rfcdateheadertodate(datestr);
  1189.  
  1190.               if not hasoverview then
  1191.                 messageid := getheaderline(filename,'message-id:');
  1192.  
  1193.               sethash(articles[numarts]^.hmessageid,messageid);
  1194.  
  1195.               if not hasoverview then
  1196.                 references := getheaderline(filename,'references:');
  1197.  
  1198. { Andrew system non-compliance, looks like }
  1199.  
  1200.               if not hasoverview then
  1201.                 begin
  1202.                   inreplyto := getheaderline(filename,'in-reply-to:');
  1203.                   inreplyto := getfirstw(inreplyto);
  1204.  
  1205.                   if length(references)+length(inreplyto)<250 then
  1206.                     if enclosedin(inreplyto,'<','>') then
  1207.                       if pos(inreplyto,references)=0 then
  1208.                         references := references+' '+inreplyto;
  1209.                 end;
  1210.  
  1211. { don't wipe out Re:'s 1 with a 0 just because there's nothing in the header }
  1212.               if numoccur('<',references)>0 then
  1213.                 articles[numarts]^.indents := numoccur('<',references);
  1214.  
  1215.               if not mailgroup then
  1216.                 begin
  1217.  
  1218.                   if not readunfiltered then
  1219.                     if artkilled(subject,from,references,filename) then
  1220.                       waskilled := true;
  1221.  
  1222. {for use with auto-select key - start of antikill}
  1223.  
  1224.                   if antikillreferences then
  1225.                     if pos(fqdn,references)<>0 then
  1226.                       wasantikilled := true;
  1227.  
  1228. { for author's use to make sure everything's working on other sites }
  1229.                   if not wasantikilled then
  1230.                     if antikillthisnewsreader then
  1231.                       if pos(dotnewsreadernamedot,messageid)<>0 then
  1232.                         wasantikilled := true
  1233.                       else if pos(oldnewsreadername,messageid)<>0 then
  1234.                         wasantikilled := true;
  1235.  
  1236.                   if not wasantikilled then
  1237.                     if artantikilled(subject,from,references,filename) then
  1238.                       wasantikilled := true;
  1239.  
  1240.                   if wasantikilled then
  1241.                     begin
  1242.                       articles[numarts]^.indents :=
  1243.                        articles[numarts]^.indents or 128;
  1244.                       xhighvideo;
  1245.                       xwrites('a');
  1246.                       xlowvideo;
  1247.                     end;
  1248.  
  1249.                 end;
  1250.  
  1251.               if waskilled and not wasantikilled then
  1252.                 begin
  1253. {if was killed, only antikilling can bring it back}
  1254.                   dec(numarts);
  1255.                 end
  1256.               else if antikilledonly and not wasantikilled then
  1257.                 begin
  1258. {if only antikilled to be shown, only antikilling can keep it}
  1259.                   dec(numarts);
  1260.                 end
  1261.               else
  1262.                 begin
  1263.                   while numoccur('>',references)>numhashedrefs do
  1264.                     ignorestring := chopfirstw(references);
  1265.  
  1266.                   sethash(articles[numarts]^.hreferences[1],
  1267.                     chopfirstw(references));
  1268.                   sethash(articles[numarts]^.hreferences[2],
  1269.                     chopfirstw(references));
  1270.                   sethash(articles[numarts]^.hreferences[3],
  1271.                     chopfirstw(references));
  1272.                   sethash(articles[numarts]^.hreferences[4],
  1273.                     chopfirstw(references));
  1274.  
  1275.                   if filenum>highestart then
  1276.                     highestart := filenum;
  1277.                 end
  1278.  
  1279.             end;
  1280.  
  1281.           showarticlesuffix;
  1282.  
  1283.           if not readnomore then
  1284.             if filenum>highestfile then
  1285.               highestfile := filenum;
  1286.         end;
  1287.  
  1288.       if hasoverview then
  1289.         begin
  1290.           morearticles := not eofoverview;
  1291.         end
  1292.       else
  1293.         begin
  1294.           findnext(fileinfo);
  1295.           morearticles := (doserror=0);
  1296.         end;
  1297.     end;
  1298.  
  1299.   if numarts=0 then
  1300.     begin
  1301.       if wroteanything then
  1302.         xwriteln;
  1303.  
  1304.       if nextwhilereading then
  1305.         begin end
  1306.       else if searchinheaders or
  1307.        searchinbody or
  1308.        searchthedate or
  1309.        searchinsubj or
  1310.        searchinname then
  1311.         warn('no articles in selected range matched')
  1312.       else
  1313.         xwritelns('no new articles');
  1314.     end
  1315.   else if wanderingnumbers then
  1316.     xwriteln;
  1317.  
  1318.   if rewoundapage and (numarts<>0) and not nextwhilereading then
  1319.     begin
  1320.       warn2
  1321.        (
  1322.        'all mail from '+currsource,
  1323.        'has been read.  the last page will be shown'
  1324.        );
  1325.     end;
  1326.  
  1327. {if there's no files at ALL, that's close enough}
  1328.  
  1329.   if (highestseen<>0) and (highestseen<alreadyread) and
  1330.    not nextwhilereading and not readnomore and startedwhereleftoff then
  1331.     begin
  1332.       warn3
  1333.        (
  1334.        'there ARE articles for this group on disk, but none close to the',
  1335.        'entry in your join file.  you may want to check for re-sequenced',
  1336.        'or missing news files.'
  1337.        );
  1338.  
  1339.       catchupunreadlastpageignore := onekeydef(
  1340.        '{c}atch up, mark all as {u}nread, {l}ast page only, {i}gnore',
  1341.        'culi','i');
  1342.  
  1343.       xwriteln;
  1344.  
  1345.       if catchupunreadlastpageignore='c' then
  1346.         begin
  1347.           warn('can only ignore or mark as unread now, sorry');
  1348.         end
  1349.       else if catchupunreadlastpageignore='u' then
  1350.         begin
  1351.           alreadyread := -1; {for updatejoin}
  1352.           updatejoin(0);
  1353.           alreadyread := 0;
  1354.         end
  1355.       else if catchupunreadlastpageignore='l' then
  1356.         begin
  1357.           warn('can only ignore or mark as unread now, sorry');
  1358.         end
  1359.       else
  1360.         begin
  1361.           {ignore}
  1362.         end;
  1363.  
  1364.     end;
  1365.  
  1366. {if all were read but filtered, show them as read to avoid scanning next time}
  1367.  
  1368.   if
  1369.    (numarts=0) and
  1370.    not nextwhilereading and
  1371.    not readnomore and
  1372.    not antikilledonly and
  1373.    not searchinheaders and
  1374.    not searchinbody and
  1375.    not searchthedate and
  1376.    not searchinsubj and
  1377.    not searchinname and
  1378.    startedwhereleftoff then
  1379.     updatejoin(highestfile);
  1380.  
  1381.   readunfiltered := false;
  1382.   antikilledonly := false;
  1383.  
  1384.   searchinheaders := false;
  1385.   searchinbody := false;
  1386.   searchthedate := false;
  1387.   searchinsubj := false;
  1388.   searchinname := false;
  1389.  
  1390.   lowestartsearched := impossiblylargeart;
  1391.  
  1392.   if morearticles and (numarts>=allocatedarts) then
  1393.     unscannedarts := true;
  1394.  
  1395. {handle 'G'oto while scanning already-read groups where O doesn't work}
  1396.  
  1397.   if xkeypressed then
  1398.     bufferedkey := xreadkey;
  1399.  
  1400.   if bufferedkey='G' then
  1401.     begin
  1402.       trysource := '';
  1403.       pickasource(trysource,trysourcekind);
  1404.       xclreolxy(1,lpp);
  1405.       if trysource<>'' then
  1406.         begin
  1407.           nextwhilereading := true;
  1408.           currsource := trysource;
  1409.           currsourcekind := trysourcekind;
  1410.           needtofindnextgroup := false;
  1411.         end;
  1412.     end
  1413.   else if bufferedkey='Q' then
  1414.     begin
  1415. {}{} {should it use confirmquit here?}
  1416.       nextwhilereading := true;
  1417.       needtofindnextgroup := false;
  1418.       currsource := '';
  1419.     end;
  1420.  
  1421.   if hasoverview then
  1422.     closeoverview;
  1423.  
  1424. end;  {procedure readinarts}
  1425.  
  1426. procedure groupinit;
  1427.  
  1428. begin { groupinit }
  1429.   numarts := 0;
  1430.   headerinmem := '';
  1431.   highestread := 0;
  1432.  
  1433.   currdir := '';
  1434.  
  1435.   if currsourcekind=sourcegroup then
  1436.     currdir := getgroupdir(currsource)
  1437.   else if currsourcekind=sourcedir then
  1438.     currdir := currsource
  1439.   else if currsourcekind=sourcefolder then
  1440.     warn('cannot yet <G>oto a folder');
  1441.  
  1442.   if currdir='' then
  1443.     begin
  1444.       if haltonunknowngroups then
  1445.         begin
  1446.           xwritelns('could not find /dir= entry for this group - location of');
  1447.           xwritelns('  news unknown.  make sure you are using the new DEFAULT');
  1448.           xwritelns('  lines instead of the old (v1.63 and lower) FORUM lines');
  1449.           xwriteln;
  1450.           xwritelns('also make sure you have not missed any forum sets if you');
  1451.           xwritelns('  used the -s or --forum-set-list options');
  1452.           shutdown(1);
  1453.         end
  1454.       else
  1455.         begin
  1456.           xwritelns('could not find directory for this group... continuing');
  1457.         end;
  1458.     end
  1459.   else
  1460.     begin
  1461.       notquietlnss('searching directory ',currdir);
  1462.  
  1463.       groupinitkills;
  1464.       groupinitantikills;
  1465.     end;
  1466. end;
  1467.  
  1468. end.
  1469.